package com.xbongbong.outerlink.impl;

import com.alibaba.fastjson.JSONObject;
import com.xbongbong.outerlink.AbstractProOuterLinkService;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.domain.entity.ext.ConditionsEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.elasticsearch.util.EsHelper;
import com.xbongbong.paas.elasticsearch.util.EsUtil;
import com.xbongbong.paas.enums.ConditionEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.factory.OptionFactory;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.field.ItemPoJo;
import com.xbongbong.paas.field.MultiUnitItemPoJo;
import com.xbongbong.paas.handle.AbstractOptionHandle;
import com.xbongbong.paas.outerlink.AbstractPaasOuterLinkService;
import com.xbongbong.paas.pojo.ProductFieldPojo;
import com.xbongbong.paas.pojo.dto.FormDataAddDTO;
import com.xbongbong.paas.pojo.dto.FormDataListDTO;
import com.xbongbong.paas.pojo.dto.OuterLinkBaseDTO;
import com.xbongbong.paas.pojo.dto.ValidateDataDTO;
import com.xbongbong.paas.pojo.vo.AfterSaveVO;
import com.xbongbong.paas.pojo.vo.PaasFormDataEsListVO;
import com.xbongbong.paas.pojo.vo.ParseSingleRowDataVO;
import com.xbongbong.paas.redis.RedisPrefixConstant;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.form.pojo.dto.ChildProductDTO;
import com.xbongbong.pro.workorder.pojo.vo.WorkOrderDataEsListVO;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.ProductCategoryEntity;
import com.xbongbong.saas.enums.ChildProductFieldEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ProductEnum;
import com.xbongbong.saas.help.SaasFormHelp;
import com.xbongbong.saas.help.SaasGetHelp;
import com.xbongbong.saas.model.ProductCategoryModel;
import com.xbongbong.saas.service.ProductService;
import com.xbongbong.saas.service.toolbox.help.AttrDecimalPrecisionHelper;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import static com.xbongbong.saas.toolbox.help.FastJsonHelper.getDoubleOrDefaultFromFormData;
import static com.xbongbong.saas.toolbox.help.FastJsonHelper.getIntegerOrDefaultFromFormData;
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;

/**
 *  产品 外链接口实现
 * @author zheng.li
 **/
@Slf4j
@Service
public class ProductOuterLinkServiceImpl extends AbstractProOuterLinkService {

    @Resource
    private SaasFormHelp saasFormHelp;

    @Resource
    private SaasGetHelp saasGetHelp;

    @Resource
    private EsHelper esHelper;

    @Resource
    private OptionFactory optionFactory;

    @Resource
    private ProductService productService;

    @Resource
    private ProductCategoryModel productCategoryModel;

    @Resource
    private AttrDecimalPrecisionHelper attrDecimalPrecisionHelper;


    @Override
    public List<Integer> businessType() {
        return Collections.singletonList(XbbRefTypeEnum.PRODUCT.getCode());
    }

    @Override
    public Map<String, FieldAttrEntity> getExplainMap(List<FieldAttrEntity> explainList, Integer businessType, String corpid, Long formId) {
        Map<String, FieldAttrEntity> explainMap = super.getExplainMap(explainList,businessType,corpid,formId);
        explainList.remove(explainMap.get(ProductEnum.IS_NOTIFY.getAttr()));
        explainMap.remove(ProductEnum.IS_NOTIFY.getAttr());
        explainList.remove(explainMap.get(ProductEnum.STOCK_NOTIFY.getAttr()));
        explainMap.remove(ProductEnum.STOCK_NOTIFY.getAttr());
        return explainMap;
    }

    @Override
    public void formatListCondition(FormDataListDTO formDataListDTO) throws XbbException {
        // 先调用父类方法
        super.formatListCondition(formDataListDTO);
        // 产品特殊实现
        String corpid = formDataListDTO.getCorpid();
        Map<String, FieldAttrEntity> explainMap = formDataListDTO.getExplainMap();
        List<ConditionsEntityExt> conditions = formDataListDTO.getConditions();
        Iterator<ConditionsEntityExt> iterator = conditions.iterator();
        List<ConditionsEntityExt> childConditionList = new ArrayList<>();
        while (iterator.hasNext()){
            ConditionsEntityExt conditionsEntityExt = iterator.next();
            Integer fieldType = conditionsEntityExt.getFieldType();
            List<Object> value = conditionsEntityExt.getValue();
            String attr = conditionsEntityExt.getAttr();

            boolean isChildField = ChildProductFieldEnum.isChildField(attr);
            if (isChildField){
                //子产品字段
                if (Objects.equals(attr,ProductEnum.SPECIFICATION.getAttr())){
                    conditionsEntityExt.setAttr(ProductEnum.SPECIFICATION_LINK_TEXT.getAttr());
                }
                childConditionList.add(conditionsEntityExt);
                iterator.remove();
            }
            if (Objects.equals(fieldType, FieldTypeEnum.COMBO.getType())
                    || Objects.equals(fieldType, FieldTypeEnum.RADIO_GROUP.getType())
                    || Objects.equals(fieldType, FieldTypeEnum.COMBO_CHECK.getType())) {
                FieldAttrEntity fieldAttrEntity = explainMap.get(attr);
                if (CollectionsUtil.isEmpty(value) || fieldAttrEntity == null) {
                    continue;
                }
                if (Objects.equals(ProductEnum.UNIT.getAttr(), fieldAttrEntity.getAttr())) {
                    List<ItemPoJo> items = fieldAttrEntity.getItems();
                    try {
                        ProductFieldPojo productFieldPojo = saasFormHelp.getProductFieldPojo(RedisPrefixConstant.PRODUCT_UNIT, ProductEnum.UNIT.getAttr(), formDataListDTO.getCorpid());
                        List<MultiUnitItemPoJo> multiItems = productFieldPojo.getMultiItems();
                        BeanUtil.copyPropertiesList(multiItems, items, ItemPoJo.class);
                    } catch (Exception e) {
                        log.error("产品多单位解析错误",e);
                    }
                    for (ItemPoJo itemPoJo : items) {
                        if (Objects.equals(itemPoJo.getIsOther(), BasicConstant.ZERO)) {
                            if (Objects.equals(itemPoJo.getText(), value.get(0))) {
                                // 因为前端回传的是text,筛选的时候需要将他转换为value值取查询
                                conditionsEntityExt.setValue(Collections.singletonList(itemPoJo.getValue()));
                                break;
                            }
                        }
                    }
                }
            }
        }
        // 规格的常用筛选
        if (!childConditionList.isEmpty()){
            BoolQueryBuilder boolQueryBuilder = boolQuery();
            EsUtil.getTermQuery(boolQueryBuilder, formDataListDTO, true);
            EsUtil.parseCondition(boolQueryBuilder,childConditionList,"",corpid,XbbRefTypeEnum.PRODUCT.getCode());
            boolQueryBuilder.mustNot(termsQuery(ProductEnum.getAttrConnectData(ProductEnum.PARENT_ID), Collections.singletonList(0)));
            List<String> childProductFieldList = new ArrayList<>();
            childProductFieldList.add(StringConstant.DATA_ID);
            childProductFieldList.add(ProductEnum.getAttrConnectData(ProductEnum.PARENT_ID));
            List<PaasFormDataEntityExt> childProductList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_PRODUCT,boolQueryBuilder,PaasFormDataEntityExt.class,childProductFieldList);
            Set<Long> parentIdList = new HashSet<>();
            parentIdList.add(-1L);
            for (PaasFormDataEntityExt entityExt : childProductList){
                parentIdList.add(entityExt.getData().getLong(ProductEnum.PARENT_ID.getAttr()));
            }
            conditions.add(new ConditionsEntityExt(FieldTypeEnum.DATAID.getAlias(),"",FieldTypeEnum.DATAID.getType(), ConditionEnum.IN.getSymbol(),new ArrayList<>(parentIdList)));
        }
        conditions.add(new ConditionsEntityExt(ProductEnum.PARENT_ID.getAttr(),"",ProductEnum.PARENT_ID.getFieldType(),ConditionEnum.EQUAL.getSymbol(),Collections.singletonList(0)));

    }


    @Override
    public void handleDataList(FormDataListDTO formDataListDTO, PaasFormDataEsListVO paasFormDataEsListVO, WorkOrderDataEsListVO workOrderDataEsListVO) throws XbbException {
        super.handleDataList(formDataListDTO,paasFormDataEsListVO,workOrderDataEsListVO);
        AbstractOptionHandle abstractOptionHandle = optionFactory.getByBusinessType(formDataListDTO.getBusinessType(), formDataListDTO.getSaasMark());
        abstractOptionHandle.setOptionsInData(formDataListDTO, paasFormDataEsListVO);
    }

    @Override
    public void handleGetData(OuterLinkBaseDTO outerLinkBaseDTO, PaasFormDataEntityExt formData, ParseSingleRowDataVO parseSingleRowDataVO, List<FieldAttrEntity> explains) throws XbbException {
        boolean multiSpec = false;
        boolean enableMultiUnit = false;
        String corpid = outerLinkBaseDTO.getCorpid();
        Long dataId = outerLinkBaseDTO.getDataId();
        // 产品编辑的时候一定要传父产品的id
        PaasFormDataEntityExt productEntity = saasGetHelp.getFormData(dataId, corpid, XbbRefTypeEnum.PRODUCT.getCode());
        if ( productEntity == null ) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_DATA_NOT_EXIST);
        }
        JSONObject productData = productEntity.getData();
        Long parentId = productData.getLong(ProductEnum.PARENT_ID.getAttr());
        if ( !Objects.equals(parentId, 0L) ) {
            dataId = parentId;
        }
        // 是否是多单位
        enableMultiUnit = Objects.equals(productData.getInteger(ProductEnum.ENABLE_MULTI_UNIT.getAttr()), BasicConstant.ONE);
        // 是否是多规格
        Integer advancedMode = getIntegerOrDefaultFromFormData(productData, ProductEnum.SPECIFICATION.getAttr(), 0);
        multiSpec = Objects.equals(advancedMode, 1);
        // 因为前端用编辑页面来处理外链分享详情页，产品分类在编辑产品时会请求接口查询分类

        ChildProductDTO childProductDTO = new ChildProductDTO();
        childProductDTO.setCorpid(corpid);
        childProductDTO.setParentProductId(Collections.singletonList(dataId));
        PaasFormDataEsListVO esDataList = productService.getChildProductList(childProductDTO);
        List<PaasFormDataEntityExt> childProductList = esDataList.getPaasFormDataESList();
        List<PaasFormDataEntityExt> multiProductList = new ArrayList<>();
        Map<Long, Object> multiProductsMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        // 所以这边将分类改成数字类型，并且这边将数据渲染好，就不会让分类字段额外查询接口了
        JSONObject newData = parseSingleRowDataVO.getResult();
        for (FieldAttrEntity fieldAttrEntity : explains) {
            String attr = fieldAttrEntity.getAttr();
            if (Objects.equals(attr, ProductEnum.CATEGORY_ID.getAttr())) {
                fieldAttrEntity.setFieldType(FieldTypeEnum.TEXT.getType());
                Long categoryId = null;
                if (Objects.nonNull(newData)) {
                    String name = "";
                    try {
                        categoryId = newData.getLong(ProductEnum.CATEGORY_ID.getAttr());
                        Map<String,Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                        map.put("corpid",corpid);
                        map.put("del",0);
                        map.put("id",categoryId);
                        List<ProductCategoryEntity> categoryEntityList = productCategoryModel.findEntitys(map);
                        if (CollectionsUtil.isNotEmpty(categoryEntityList)) {
                            name = categoryEntityList.get(0).getName();
                        }
                    } catch (Exception e) {
                        log.error("outerLinkServiceImpl.get解析产品外链分享分类出错", e);
                    }
                    if(categoryId!=null){
                        newData.put(ProductEnum.CATEGORY_ID.getAttr(), name);
                    }

                }
            } else if(Objects.equals(attr, ProductEnum.COST.getAttr())){
                String priceStr;
                if (multiSpec) {
                    // 将子产品按照价格排序
                    priceStr = productService.getPriceOrCostRegion(childProductList, attr, fieldAttrEntity.getAccuracy());
                } else {
                    Double price = getDoubleOrDefaultFromFormData(childProductList.get(0).getData(), attr, 0D);
                    priceStr = attrDecimalPrecisionHelper.formatMoneyPrecision(price, fieldAttrEntity);
                }
                newData.put(attr, priceStr);
            } else if (Objects.equals(attr, ProductEnum.PRICE.getAttr())){
                int priceAccuracy = fieldAttrEntity.getAccuracy() == null ? AttrDecimalPrecisionHelper.DEFAULT_PRECISION : fieldAttrEntity.getAccuracy();
                if (enableMultiUnit) {
                    productService.handleMultiPrice(multiProductsMap, multiProductList,corpid, dataId, priceAccuracy);
                }
                String priceStr;
                if (enableMultiUnit) {
                    //多单位产品都需要做价格排序
                    priceStr = productService.getPriceOrCostRegion(multiProductList, attr, fieldAttrEntity.getAccuracy());
                } else if (multiSpec) {
                    // 将子产品按照价格排序
                    priceStr = productService.getPriceOrCostRegion(childProductList, attr, fieldAttrEntity.getAccuracy());
                } else {
                    Double price = getDoubleOrDefaultFromFormData(childProductList.get(0).getData(), attr, 0D);
                    priceStr = attrDecimalPrecisionHelper.formatMoneyPrecision(price, fieldAttrEntity);
                }
                newData.put(attr, priceStr);
            }
        }
    }

    @Override
    public void beforeSave(ValidateDataDTO validateDataDTO) throws XbbException {
        super.beforeSave(validateDataDTO);
    }


    @Override
    public AfterSaveVO insert(FormDataAddDTO formDataAddDTO, PaasFormDataEntity paasFormDataEntity, PaasFormEntityExt paasFormEntityExt) throws XbbException {
        return super.insert(formDataAddDTO,paasFormDataEntity,paasFormEntityExt);
    }
}
